(function($, doc){
    /**
     * jQuery基础扩展.
     * @module jquery base plugins
     */
    
    /**
     * jQuery ajax preprocess.
     */
    $.ajaxPrefilter( function( options, originalOptions, jqXHR ) {  
        if(originalOptions['isPrefilter'] === false){
            //若用户指定不使用默认的prefilter.
            return;
        }  
        var ajaxCfg = ujs.getConfig('ajax');    
        $.extend(options, ajaxCfg);
        //若ajax请求参数processUrl : false或 url地址以http打头，则使用原地址发送请求.
        if(originalOptions['processUrl'] !== false && !options['url'].startsWith('http')){        
            if(!options['url'].startsWith('$')){
                //api限定路径.
                var apiPrefix = ajaxCfg['apiPathPrefix']; 
                if( apiPrefix ){
                    options['url'] = apiPrefix + options['url'];    
                }            
                if( ajaxCfg.processUrl){
                    ajaxCfg.processUrl(options, originalOptions);    
                }         
            } else {
                //若 url以 $ 打头，则去掉它.
                options['url'] = options['url'].substring(1);
            }
        }   
        //process data.    
        if( ajaxCfg.processData && originalOptions['processData'] !== false){
            ajaxCfg.processData(options, originalOptions);    
        }    
    });
    
    //--------------------------------------------------------------------------------
        
    /**
     * 获取元素的ID.
     */
    $.fn.id = function(){
        return $(this).attr('id');
    };
    
    /**
     * 获取多个元素的IDs.
     */
    $.fn.ids = function(){
        return $(this).map(function(){
            return $(this).attr('id');  
        });
    };
    
    //--------------------------------------------------------------------------------
    
    /**
     * 判断jQuery对象是否为空。
     */
    $.fn.isEmpty = $.fn.isNotExsit = function(){
        return !$(this).size();
    };
    
    $.fn.isExist = function(){
        return !($(this).isEmpty());
    };
    
    //--------------------------------------------------------------------------------
    
    /**
     * 提取元素上的配置信息，配置属性以 "cfg-" 开关。如：
     * 
     * @param {Object} config
     */
    $.fn.extractConfig = function(config){
        if(!config){
            config = {};
        }
        var cfg = $.extend({}, config);                        
        var attrs = $(this)[0].attributes;                    
        for(var i = 0,attrsCount = attrs.length; i<attrsCount; i++){
            var attrName = attrs[i].name;
            if(attrName.indexOf('cfg-') === 0){                 
                JSON.setPath(cfg, attrName.replace(/cfg\-/gi,''), attrs[i].value);
            }
        }    
        return cfg;
    };
    
    //--------------------------------------------------------------------------------
    
    /**
     * 禁用.
     */
    $.fn.disable = function(){
        $(this).each(function(){
            var $self = $(this);
            $self.attr('disabled','disabled').addClass('disabled').find(':input').prop("disabled", true);
            $self.find('a').addClass('disabled').attr('onclick', 'return false;');
        });
        return this;
    };
    /**
     * 启用.
     */
    $.fn.enable = function(){
        $(this).each(function(){
            var $self = $(this);
            $self.removeAttr('disabled').removeClass('disabled').find(':input').prop("disabled", false);
            $self.find('a').removeClass('disabled').attr('onclick', '');
        });
        return this;
    };
    
    //--------------------------------------------------------------------------------
    
    /**
     * 只读.
     */
    $.fn.readonly = function(){
        $(this).each(function(){
            var $self = $(this);
            $self.attr('readonly','readonly').addClass('readonly');
        });
        return this;
    };
    
    /**
     * 可写.
     */
    $.fn.editable = function(){
        $(this).each(function(){
            var $self = $(this);
            $self.removeAttr('readonly').removeClass('readonly');
        });
        return this;
    };
    
    //--------------------------------------------------------------------------------
    
    /**
     * 选中复选框
     */
    $.fn.check = function(checkStateChangeHandler){    
        $(this).each(function(){
            var $checkbox = $(this);
            if(Type.isFunction(checkStateChangeHandler)){
                $checkbox.change(function(e) {
                    checkStateChangeHandler.call(this, $(this).is(":checked")); 
                });    
            } else {
                $checkbox.prop('checked', true);
            }
        });
        return this;
    };
    
    /**
     * 取消选中复选框
     */
    $.fn.uncheck = function(){
        $(this).each(function(){
            $(this).prop('checked', false);
        });
        return this;
    };
    
    //--------------------------------------------------------------------------------
    
    $.fn.contains = function(child){
        if(child){
            if(child.constructor === $){
                child = child.get(0);
            }
            return $.contains(this.get(0), child);    
        }    
    };
        
    //-----------------------------------------------------------------
    
    $.fn.getVisibleChildren = function(){
        var $parent = $(this);
        var $children = $parent.find('>*');
        var visibleChildren = [];
        $children.each(function(){
            var $child = $(this),
                childHeight = $child.outerHeight(),
                position = $child.position();
            if(position.top > -childHeight && position.top < $parent.outerHeight()){
                visibleChildren.add($child);
            }
        });
        return visibleChildren;
    };
    
    /**
     * 获取文本节点.
     */
    $.fn.textNodes = function(){
        return $(this).contents().filter(function() {
            return this.nodeType === 3;
        });  
    };
    
    //-----------------------------------------------------------------
    
    /**
     * 隐藏事件冒泡与默认事件逻辑.
     * @param {Object} e
     */
    $.stopEvent = function(e){
        e.stopPropagation();
        e.preventDefault();
    };
    
    //事件绑定.
    $.addEvent = function(element, type, handler) {
        if (element.addEventListener) {
            element.addEventListener(type, handler, false);
        } else {
            if(!addEvent.guid){
                addEvent.guid = 1;
            }
            // assign each event handler a unique ID
            if (!handler['$$GUID'])
                handler['$$GUID'] = addEvent.guid++;
            // create a hash table of event types for the element
            if (!element.events)
                element.events = {};
            // create a hash table of event handlers for each element/event pair
            var handlers = element.events[type];
            if (!handlers) {
                handlers = element.events[type] = {};
                // store the existing event handler (if there is one)
                if (element["on" + type]) {
                    handlers[0] = element["on" + type];
                }
            }
            // store the event handler in the hash table
            handlers[handler['$$GUID']] = handler;
            // assign a global event handler to do all the work
            element["on" + type] = function(event) {
                var returnValue = true;
                // grab the event object (IE uses a global event object)
                if(!event){
                    event = ( ( this.ownerDocument || this.document || this ).parentWindow || window ).event;
                    event.preventDefault = function() {
                        this.returnValue = false;
                    };
                    event.stopPropagation = function() {
                        this.cancelBubble = true;
                    };
                }    
                // get a reference to the hash table of event handlers
                var handlers = this.events[event.type];
                // execute each event handler
                for (var i in handlers) {
                    this.$$handleEvent = handlers[i];
                    if (this.$$handleEvent(event) === false) {
                        returnValue = false;
                    }
                }
                return returnValue;
            };
        }
    };
    
    //------------------------------------------------------------------
    
    //获取元素位置.
    $.fn.getPosition = function() {
        var ele = $(this).get(0);
        var left = 0;
        var top = 0;
        var width = String.toInt(ele.style.width);
        var height = String.toInt(ele.style.height);
        var offsetWidth = ele.offsetWidth;
        var offsetHeight = ele.offsetHeight;
    
        while (ele.offsetParent) {
            left += ele.offsetLeft + (ele.currentStyle ? String.toInt(ele.currentStyle.borderLeftWidth) : 0);
            top += ele.offsetTop + (ele.currentStyle ? String.toInt(ele.currentStyle.borderTopWidth) : 0);
            ele = ele.offsetParent;
        }
        left += ele.offsetLeft + (ele.currentStyle ? String.toInt(ele.currentStyle.borderLeftWidth) : 0);
        top += ele.offsetTop + (ele.currentStyle ? String.toInt(ele.currentStyle.borderTopWidth) : 0);
    
        return {
            left : left,
            top : top,
            width : width,
            height : height,
            offsetWidth : offsetWidth,
            offsetHeight : offsetHeight
        };
    };
    
    //-------------------------------------------------------------------------
    
    /**
     * 延迟加载图片.
     * @param {Function} cb : 生成src 
     * @param {Function} loadedHandler : 加载完成事件
     */
    $.lazyLoadImage = function(cb, loadedHandler) {
        var $image = $(this);
        var src = $image.attr('src'), 
            xsrc = $image.attr('xsrc');
        if (src != xsrc) {
            if(loadedHandler){
                $image.load(function(){
                    loadedHandler.call(this);       
                });
            }
            $image.attr('src', cb ? cb(xsrc) : xsrc);
        }
    };
    
    //----------------------------------------------------------------------------
    
    //获取document对象.
    $.getDocument = function(element) {
        if (element) {
            if (element instanceof $) {
                element = element.length > 0 ? element[0] : undefined;
            }
            if (element && element.nodeName.toLowerCase() == 'iframe') {
                return element.contentWindow.document;
            }
        }
        return document;
    };
    
    //获取选择的文本.
    $.getSelectionText = function(element) {
        var doc = $.getDocument(element);
        if (doc.selection) {
            return doc.selection.createRange().text;
        } else {
            return doc.getSelection().toString();
        }
    };
    
    //------------------------------------------------------------------------------
    
    //根据属性值选择元素.
    $.getElementByAttributeValue = function(tagName, attributeName, attributeValue) {
        var elements = this.editorDoc.getElementsByTagName(tagName);
        for (var i = 0, len = elements.length; i < len; i++) {
            if (elements[i].getAttribute(attributeName) == attributeValue) {
                return elements[i];
            }
        }
        return false;
    };
    
    //-------------------------------------------------------------------------------
    
    $.onReady = function(fun){            
        if( ['loaded', 'interactive', 'complete'].contains(doc.readyState.toLowerCase()) ){
            return fun();
        }
        if (doc.addEventListener) {
            doc.addEventListener("DOMContentLoaded", fun, false);
        } else if (/WebKit/i.test(navigator.userAgent)) {
            var _timer = setInterval(function() {
                if (/loaded|complete/.test(doc.readyState)) {
                    fun();
                    if(_timer)  clearInterval(_timer);
                }
            }, 10);
        } else {        
            window.onload = fun;    
        }  
    };    
})($, document);